package ArithmeticObjects;
import java.io.IOException;

import utils.ByteTree;

/**
 * Representing a large number as an arithmetic object 
 * @author Idan
 */
public class LargeNumberObject extends Element{

	/**
	 * creates a LargeNumberObject from a given ByteTree representing it
	 * @param bt ByteTree representing the LargeNumberObject
	 */
	public LargeNumberObject(ByteTree bt)
	{
		value = bt.getNumber();
	}
	
	/**
	 * creates a LargeNumberObject from a LargeNumber
	 * @param num a LargeNumber representing the LargeNumberObject
	 * @throws Exception in case the construction failed
	 */
	public LargeNumberObject(LargeNumber num) throws Exception {
		value = num;  
	}

	/**
	 * creates a LargeNumberObject from an int
	 * @param n the integer representing the LargeNumberObject
	 * @throws Exception in case the construction failed
	 */
	public LargeNumberObject(int n) throws Exception {
		value = new LargeNumber(n);
	}
	
	@Override
	public Element add(Element elementA,
			Element... elements) throws Exception {
		if (!(elementA instanceof LargeNumberObject))
			throw new Exception("Wrong class, Expected: LargeNumberObject, got: " + elementA.getClass().getName());
		LargeNumber val = value.add(elementA.getValue());
		for (int i=0; i<elements.length; i++)
		{
			if (!(elements[i] instanceof LargeNumberObject))
				throw new Exception("Wrong class, Expected: LargeNumberObject, got: " + elements[i].getClass().getName());
			val = val.add(elements[i].getValue());
		}
		return new LargeNumberObject(val);
	}
	
	@Override
	public Element subtract(Element elementA) throws Exception {
		if (!(elementA instanceof LargeNumberObject))
			throw new Exception("Wrong class, Expected: LargeNumberObject, got: " + elementA.getClass().getName());
		LargeNumber val = value.subtract(elementA.getValue());
		return new LargeNumberObject(val);
	}
	
	@Override
	public Element multiply(Element elementA,
			Element... elements) throws Exception {
		if (!(elementA instanceof LargeNumberObject))
			throw new Exception("Wrong class, Expected: LargeNumberObject, got: " + elementA.getClass().getName());
		LargeNumber val = value.multiply(elementA.getValue());
		for (int i=0; i<elements.length; i++)
		{
			if (!(elements[i] instanceof LargeNumberObject))
				throw new Exception("Wrong class, Expected: LargeNumberObject, got: " + elements[i].getClass().getName());
			val = val.multiply(elements[i].getValue());
		}
		return new LargeNumberObject(val);
	}
	
	@Override
	public Element divide(Element elementA) throws Exception {
		if (!(elementA instanceof LargeNumberObject))
			throw new Exception("Wrong class, Expected: LargeNumberObject, got: " + elementA.getClass().getName());
		LargeNumber val = value.divide(elementA.getValue());
		return new LargeNumberObject(val);
	}

	@Override
	public Element power(Element exponent) throws Exception {
		LargeNumber val = value.power(exponent.getValue());
		return new LargeNumberObject(val);
	}
	
	@Override
	public Element additiveInverse() throws Exception {
		return this;
	}
	
	@Override
	public int compareTo(Element elementA) throws Exception {
		if (!(elementA instanceof LargeNumberObject))
			throw new Exception("Wrong class, Expected: LargeNumberObject, got: " + elementA.getClass().getName());
		return value.compareTo(elementA.getValue());
	}
	
	@Override
	public String toString() {
		return value.toString() + "\n";
	}
	
	@Override
	public ByteTree getByteTree() throws IOException {
		return ByteTree.CreateLeaf(value.toByteArray());
	}
}
